package com.ln.design.mode.behavior.interpret.example1;

import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.HashMap;
import java.util.Map;

/**
 * 解释器模式 实例一
 *
 * @Author zhangj
 * @Date 2022/12/3 14:55
 */
public class ExpressionMode_1 {

    /**
     *  上下文
     */
    static class Context {

        /**
         * 运算变量
         */
        private Map<Variable, Integer> variableMap = new HashMap<>();

        /**
         * 给运算变量赋值
         */
        public void assign(Variable var, Integer val) {
            variableMap.put(var, val);
        }

        public Integer getValue(Variable variable) {
            return variableMap.get(variable);
        }

    }

    /**
     * 文法接口
     */
    interface Expression<T> {

        /**
         * 文法解释
         */
        T interpret(Context context);

    }

    /**
     *  抽象文法类
     */
    abstract static class AbstractExpression implements Expression<Integer>{
    }


    /**
     *  抽象非终止的文法类
     */
    @Data
    @AllArgsConstructor
    abstract static class AbstractNonTerminationExpression extends AbstractExpression {

        protected AbstractExpression left;
        protected AbstractExpression right;

        /**
         * 解释
         */
        @Override
        public abstract Integer interpret(Context context);

        @Override
        public String toString() {
            return "(" + left.toString() + " - " + right.toString() + ")";
        }

    }

    /**
     *  非终止运算符 - 减法
     */
    public static class Minus extends AbstractNonTerminationExpression {

        public Minus(AbstractExpression left, AbstractExpression right) {
            super(left, right);
        }

        /**
         * 解释：减法
         */
        @Override
        public Integer interpret(Context context) {
            return left.interpret(context) - right.interpret(context);
        }
    }

    /**
     *  非终止运算符 - 加法
     */
    public static class Plus extends AbstractNonTerminationExpression {

        public Plus(AbstractExpression left, AbstractExpression right) {
            super(left, right);
        }

        /**
         * 解释：加法
         */
        @Override
        public Integer interpret(Context context) {
            return left.interpret(context) + right.interpret(context);
        }
    }

    /**
     *  终止运算符 - 值
     */
    @Data
    public class Value extends AbstractExpression {

        private int val;

        /**
         * 解释：获取值
         */
        @Override
        public Integer interpret(Context context) {
            return val;
        }
    }


    /**
     *  终止运算符 - 变量表达式
     */
    @Data
    @AllArgsConstructor
    public static class Variable extends AbstractExpression {

        private String name;

        /**
         * 解释
         */
        @Override
        public Integer interpret(Context context) {
            return context.getValue(this);
        }

        @Override
        public String toString() {
            return name;
        }

    }

    public static void main(String[] args) {
        // 定义上下文
        Context context = new Context();

        // 定义运算变量
        Variable a = new Variable("a");
        Variable b = new Variable("b");
        Variable c = new Variable("c");
        Variable d = new Variable("d");
        Variable e = new Variable("e");

        // 赋值
        context.assign(a, 1);
        context.assign(b, 2);
        context.assign(c, 3);
        context.assign(d, 4);
        context.assign(e, 5);

        AbstractExpression expression = new Plus(new Plus(a, b), new Minus(c, new Plus(d, e)));

        System.out.println(expression + "=" + expression.interpret(context));

    }



}
